/*
 *      Time.c
 *      
 *      Copyright 2009 Daniele Ricci <denn86@gmail.com>, Luca Saccagi <luksak86@gmail.com>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */

#ifndef _TIME_IMPL
#define _TIME_IMPL

#include "Time.h"

/**\brief Funzione di immissione nella struttura di indicizzazione del timestamp di un nuovo alert.
 * \param AlertList *root Puntatore alla posizione in cui andrà inserito l'alert
 * \param xmlNode *father Puntatore al nodo XML contenente l'alert
 */
#ifdef _WIN32 
static void setTime(AlertList *root, xmlNode *father){
#else
void setTime(AlertList *root, xmlNode *father){
#endif
	if((strncmp((char *)father->name,"CreateTime",strlen((char *)father->name))==0)&&(father->children!=NULL)){
		indexTime(root,father,'c');
	}
	if((strncmp((char *)father->name,"AnalyzerTime",strlen((char *)father->name))==0)&&(father->children!=NULL)){
		indexTime(root,father,'a');
	}
	if((strncmp((char *)father->name,"DetectTime",strlen((char *)father->name))==0)&&(father->children!=NULL)){
		indexTime(root,father,'d');
	}
}
/**\brief Ricerca la posizione di inserimento del nuovo alert nella struttura di indicizzazione.
 * 
 * Nella struttura di indicizzazione viene effettuata la ricerca della posizione di inserimento del nuovo alert:
 * dapprima si cerca la lista corrispondente all'anno, una volta trovatala si richiama la funzione scanYear per reperire la posizione nella lista dell'anno oppure, in caso di lista vuota, viene creato un nuovo nodo.
 * \param iDay *today Lista degli anni in cui è presente un alert in questo giorno
 * \param int year Anno dell'alert
 * \param long int ts Timestamp dell'alert
 * \return dailyAlertList * Puntatore al nodo in cui inserire l'alert
 */
#ifdef _WIN32 
static dailyAlertList *lastTimestamp(iDay *today, int year, long int ts){
#else
dailyAlertList *lastTimestamp(iDay *today, int year, long int ts){
#endif
	yList *curyear;
	dailyAlertList *curday;
	
	if(today->top == NULL){
		today->top=(yList *)malloc(sizeof(yList));
		curday=newyList(today->top,year);
	}else{
		curyear=today->top;
		while(curyear->next != NULL && curyear->yy != year){
			curyear=curyear->next;
		}
		if(curyear->next == NULL){
			if(curyear->yy == year){
				curday=scanYear(curyear,ts);
			}else{
				curyear->next=(yList *)malloc(sizeof(yList));
				curday=newyList(curyear->next,year);
			}
		}else{
			curday=scanYear(curyear,ts);
		}
	}
	return curday;
}
/**\brief Inserisce l'alert nella lista corrispondente all'anno riportato nel timestamp.
 * 
 * Nella lista dell'anno passata come parametro, ricerca la posizione in cui inserire il nuovo alert, vi crea un nodo vuoto e ne restituisce il puntatore.
 * \param yList *curyear Lista dell'anno corrispondente a quello dell'alert
 * \param long int ts Timestamp dell'alert attuale che consente di cercare la posizione esatt di inserimento.
 * \return dailyAlertList * Puntatore al nuovo nodo creato, in cui inserire il nuovo alert
 */
#ifdef _WIN32 
static dailyAlertList *scanYear(yList *curyear, long int ts){
#else
dailyAlertList *scanYear(yList *curyear, long int ts){
#endif
	dailyAlertList *cur,*old;
	
	cur=curyear->top;
	if(cur == NULL){
		cur=tsHeadIns(curyear,NULL);
	}else{	
		old=cur;
		while((cur->next != NULL) && (cur->ts<ts)){
			old=cur;		
			cur=cur->next;
		}
		if(cur->next == NULL){
			if(cur->ts>ts){
				if(old==cur){
					cur=tsHeadIns(curyear,cur);
				}else{
					cur=tsBetweenIns(curyear,old,cur);
				}
			}else{
				cur=tsBottomIns(curyear,cur);
			}
		}else{
			if(old==cur){
				cur=tsHeadIns(curyear,cur);
			}else{
				cur=tsBetweenIns(curyear,old,cur);
			}
		}
	}
	return cur;
}
/**\brief Funzione di indicizzazione degli alert tramite timestamp
 * 
 * Dopo aver estratto dal nodo XML da inserire il timestamp, lo pone nella struttura di indicizzazione immediatamente dopo il nodo con il timestamp minore e più vicino a quello da inserire.
 * \param AlertList *root Puntatore alla lista in cui verrà inserito il nodo attuale
 * \param xmlNode *father Puntatore al nodo da inserire
 * \param char mode Tipo di timestamp (create, detect o analyzer)
 */
#ifdef _WIN32 
static void indexTime(AlertList *root,xmlNode *father, char mode){
#else
void indexTime(AlertList *root,xmlNode *father, char mode){
#endif
	int year;
	int mm,dd,hh,mn,ss;
	int daycount;
	unsigned char month,day,hour,min,sec;
	dailyAlertList *cur;
	long int ts;
	
	if(father->CONTENT!=NULL){
		sscanf((char *)father->CONTENT,"%d-%d-%dT%d:%d:%dZ",&year,&mm,&dd,&hh,&mn,&ss);
		month=mm;
		day=dd;
		hour=hh;
		min=mn;
		sec=ss;
		ts=timestamp(hh,mn,ss);
		daycount=dayOfTheYear(dd,mm);
		switch(mode){
			case 'c':
				cur=lastTimestamp( &CreateTime[daycount], year, ts);
			break;
			case 'd':
				cur=lastTimestamp( &DetectTime[daycount], year, ts);
			break;
			case 'a':
				cur=lastTimestamp( &AnalyzerTime[daycount], year, ts);
			break;
		};
		cur->referred=root;
		cur->ts=ts;
		cur->yy=year;
		cur->mm=month;
		cur->dd=day;
		cur->hh=hour;
		cur->min=min;
		cur->sec=sec;
		root->time_index=cur;
	}	
}

#ifdef _WIN32 
static int timestamp(int h,int m, int s){
#else
inline int timestamp(int h,int m, int s){
#endif
	return 100*100*h+100*m+s;	
}

#ifdef _WIN32 
static int dayOfTheYear(int day, int month){
#else
inline int dayOfTheYear(int day, int month){
#endif
	int numdays[]={31,29,31,30,31,30,31,31,30,31,30,31};
	int d=0,i;
	
	for(i=1;i<month;i++){
		d+=numdays[i-1];
	}
	d--;
	d+=day;	
	return d;
}

#ifdef _WIN32 
static yList *modeTime(int d,char mode){
#else
inline yList *modeTime(int d,char mode){
#endif
	switch(mode){
		case 'c':
			return CreateTime[d].top;
		break;
		case 'd':
			return DetectTime[d].top;
		break;
		case 'a':
			return AnalyzerTime[d].top;
		break;
	};
	return NULL;
}
/**\brief Funzione di parsing delle query relative ai timestamp
 *
 * Questa funzione viene richiamata da pTree_newnode per effettuare il parsing della sezione where delle query relative
 * atimestamp.<br>
 * Nella fase di inizializzazione occorre inserire il puntatore a questa funzione nell'elemento della lista relativo
 * ai timestamp.<br>
 * \param this Nodo dell'albero di esecuzione che contiene l'istruzione di filtraggio sui timestamp
 * \param where Stringa contenente la sezione where della query
 * \param index Indice dell'inizio della porzione della stringa \awhere relativo al filtro sui timestamp
 * \param i Indice di lettura della stringa \awhere
 */
#ifdef _WIN32 
static  int parse_time(processingTree *this,char *where,int index,int *i){
#else
int parse_time(processingTree *this,char *where,int index,int *i){
#endif
	int y,m,d,h,min,s,y2,m2,d2,h2,min2,s2;
	int dayinmonth[12]={31,29,31,30,31,30,31,31,30,31,30,31};
	char *operation;
	char t=0;
	bool btw=false;

	while((where[*i]!=' ') && (where[*i]!=')') && (where[*i]!=WHERE_T)){
		*i=*i+1;
	}
	if((operation=(char *)calloc(sizeof(char),*i-index+1))==NULL){
		return -451;
	}
	strncpy(operation,&where[index],*i-index+1);		
	if(operation[3]=='='){
		if(sscanf(operation,"TS%c=%d-%d-%d,%d:%d:%d",&t,&y,&m,&d,&h,&min,&s)==0){
			free(operation);
			operation=NULL;
			return -501;
		}
	}else if(operation[3]=='!'){
		if(sscanf(operation,"TS%c!=%d-%d-%d,%d:%d:%d",&t,&y,&m,&d,&h,&min,&s)==0){
			free(operation);
			operation=NULL;
			return -501;
		}
	}else if(operation[3]=='_'){
			btw=true;
		if(operation[7]=='='){
			if(sscanf(operation,"TS%c_BTW=%d-%d-%d,%d:%d:%d|%d-%d-%d,%d:%d:%d",&t,&y,&m,&d,&h,&min,&s,&y2,&m2,&d2,&h2,&min2,&s2)==0){
				free(operation);
				operation=NULL;
				return -501;
			}
		}else if(operation[7]=='!'){
			if(sscanf(operation,"TS%c_BTW!=%d-%d-%d,%d:%d:%d|%d-%d-%d,%d:%d:%d",&t,&y,&m,&d,&h,&min,&s,&y2,&m2,&d2,&h2,&min2,&s2)==0){
				free(operation);
				operation=NULL;
				return -501;
			}
		}else{
			free(operation);
			operation=NULL;
			return -501;
		}
	}
	if(t=='a'||t=='d'||t=='c'){
		if(m==2){
			if((y%4==0 && y%100!=0) || (y%400==0)){
				dayinmonth[1]=29;
			}else{
				dayinmonth[1]=28;
			}
		}
		if(d<=dayinmonth[(m-1)%12]){
			if(btw==true){
				if(m2==2){
					if((y2%4==0 && y2%100!=0) || (y2%400==0)){
						dayinmonth[1]=29;
					}else{
						dayinmonth[1]=28;
					}
				}
				if(d2<=dayinmonth[(m2-1)%12]){
					if(((h2<0)||(h2>24))||((min2<0)||(min2>60))||((s2<0)||(s2>60))||((m2<0)||(m2>12))||(d2<0)){	
						free(operation);
						operation=NULL;
						return -501;
					}
				}
			}
			if(((h>=0)&&(h<24))&&((min>=0)&&(min<60))&&((s>=0)&&(s<60))&&((m>0)&&(m<=12))&&(d>0)){
				this->OP=(char *)calloc(sizeof(char),*i-index+1);
				strncpy(this->OP,operation,*i-index);
				free(operation);
				operation=NULL;
				while(where[*i]==' '){
					*i=*i+1;
				}
				if(where[*i]!=WHERE_T){
					this->nextbro=(processingTree *)malloc(sizeof(processingTree));
					setBro(this);
					*i=pTree_newnode(this->nextbro,where,*i,NEW_BRO);
				}
				return *i;
			}
		}
	}
	free(operation);
	operation=NULL;
	return -501;
}
/**\brief Cancellazione dei nodi dalla struttura di indicizzazione degli indirizzi ip
 *
 * Questa funzione si occupa della rimozione dei nodi relativi a un dato alert dalla struttura di indicizzazione
 * degli indirizzi ip.
 * \param to_delete Puntatore all'alert da rimuovere
 */
#ifdef _WIN32 
static void del_time_index(AlertList *to_delete){ 
#else
void del_time_index(AlertList *to_delete){
#endif
	dailyAlertList *time_delete;
	yList *ad_top_point;
	
	if(to_delete->time_index!=NULL){
		time_delete=to_delete->time_index;
		if(time_delete->prev!=NULL){
			if(time_delete->prev!=time_delete){
				time_delete->prev->next=time_delete->next;
				if(time_delete->next!=NULL){
					time_delete->next->prev=time_delete->prev;
				}
			}else{
				ad_top_point=(yList *)time_delete->top;
				if(time_delete->next!=NULL){
					time_delete->next->prev=time_delete->next;
				}
				ad_top_point->top=time_delete->next;
			}
		}
		free(time_delete);
		time_delete=NULL;
	}
}
/**\brief Esegue una prima scrematura determinando che tipo di filtro occorre usare
 *
 * In base alla stringa di identificazione presente nel nodo del processingTree che viene passato come parametro si
 * determina quale tipo di filtro eseguire.
 * \param processingTree *this Puntatore al nodo dell'albero di esecuzione che determina l'operazione da eseguire
 * \param stringList *sel Puntatore alla lista delle stringhe delle sezione select che determinano quali campi inviare
 * \param VortexConnection *cn Connessione sulla quale inviare i risultati
 * \param VortexChannell *ch Canale sul quale inviare i risultati
 * \return xmlNodeList * Puntatore alla lista dei risultati
 */
#ifdef _WIN32 
static xmlNodeList *time_filters(processingTree *this,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#else
xmlNodeList *time_filters(processingTree *this,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	if((strncasecmp(this->OP,"TSa=",4)==0) || (strncasecmp(this->OP,"TSc=",4)==0) || (strncasecmp(this->OP,"TSd=",4)==0)){
		return (this->father==this)?TimeFilter(this->sign_mode,this->sign_num,this->step_num,&this->OP[4],this->OP[2],sel,cn,ch):TimeFilter(this->sign_mode,this->sign_num,this->step_num,&this->OP[4],this->OP[2],NULL,NULL,NULL);
	}
	if((strncasecmp(this->OP,"TSa!=",5)==0) || (strncasecmp(this->OP,"TSc!=",5)==0) || (strncasecmp(this->OP,"TSd!=",5)==0)){
		return (this->father==this)?notTimeFilter(this->sign_mode,this->sign_num,this->step_num,&this->OP[5],this->OP[2],sel,cn,ch):notTimeFilter(this->sign_mode,this->sign_num,this->step_num,&this->OP[5],this->OP[2],NULL,NULL,NULL);
	}
	if((strncasecmp(this->OP,"TSa_BTW=",8)==0) || (strncasecmp(this->OP,"TSc_BTW=",8)==0) || (strncasecmp(this->OP,"TSd_BTW=",8)==0)){
		return (this->father==this)?betweenTime(this->sign_mode,this->sign_num,this->step_num,&this->OP[8],this->OP[2],sel,cn,ch):betweenTime(this->sign_mode,this->sign_num,this->step_num,&this->OP[8],this->OP[2],NULL,NULL,NULL);
	}
	if((strncasecmp(this->OP,"TSa_BTW!=",9)==0) || (strncasecmp(this->OP,"TSc_BTW!=",9)==0) || (strncasecmp(this->OP,"TSd_BTW!=",9)==0)){
		return (this->father==this)?notbetweenTime(this->sign_mode,this->sign_num,this->step_num,&this->OP[9],this->OP[2],sel,cn,ch):notbetweenTime(this->sign_mode,this->sign_num,this->step_num,&this->OP[9],this->OP[2],NULL,NULL,NULL);
	}
	return NULL;
}

/**\brief Filtro sul timestamp
 *
 * Effettua la ricerca in base al timestamp che viene passato, restituendo una lista ordinata di tutti gli alert in cui il timestamp corrisponde a quello passato come parametro.
 * \param const char *tstamp Il timestamp da utilizzare come rifericìmento nella ricerca
 * \param char mode Indica il tipo di timestamp (create, detect, analyzer)
 * \param stringList *sel Lista contenente la query, o NULL per i nodo intermedi dell'albero di esecuzione, che non devono restituire il risultato all'esterno
 * \param VortexConnection *cn Connessione su cui inviare la lista di alert, nel caso in cui *sel non sia NULL
 * \param VortexChannel *ch Canale su cui inviare gli alert nel caso in cui *sel non sia NULL
 * \return xmlNodeList * Lista ordinata contenente gli alert positivi alla ricerca, assume valore NULL nel caso in cui i dati debbano essere inviati direttamente sulla connessione (*sel diverso da NULL)
 */
#ifdef _WIN32 
static xmlNodeList *TimeFilter(unsigned char sign_mode,int sign_num,int step_num,const char *tstamp, char mode,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#else
xmlNodeList *TimeFilter(unsigned char sign_mode,int sign_num,int step_num,const char *tstamp, char mode,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	int year,month,day,hour,min,sec,cnt=0;
	int d;
	unsigned char hh,mn,ss;
	long int ts;
	yList *curyear;
	dailyAlertList *curday;
	xmlNodeList *positive;
	AlertList *local;
	
	positive=NULL;
	positive=newxmlNodeList();
	sscanf(tstamp,"%d-%d-%d,%d:%d:%d",&year,&month,&day,&hour,&min,&sec);
	hh=hour;
	mn=min;
	ss=sec;
	ts=timestamp(hour,min,sec);
	d=dayOfTheYear(day,month);
	curyear=modeTime(d,mode);
	while(curyear != NULL){
		if(curyear->yy == year){
			curday=curyear->top;
			while(curday != NULL){
				local=curday->referred;
				if((ts==curday->ts) && ((local->match[sign_num]&pow2[step_num])==0)^sign_mode){
					if(sel==NULL){
						setNodePointer(positive,curday->referred);
						cnt++;
					}else{
						visualMessage(sign_num,step_num,curday->referred,sel,cn,ch);
					}
				}
				curday=curday->next;
			}
		}
		curyear=curyear->next;
	}

	return (cnt>0)? positive : freexmlNodeList(positive);
}

/**\brief Filtro negato sul timestamp
 *
 * Effettua la ricerca negata in base al timestamp che viene passato, restituendo una lista ordinata di tutti gli alert in cui il timestamp è diverso.
 * \param const char *tstamp Il timestamp da utilizzare come rifericìmento nella ricerca
 * \param char mode Indica il tipo di timestamp (create, detect, analyzer)
 * \param stringList *sel Lista contenente la query, o NULL per i nodo intermedi dell'albero di esecuzione, che non devono restituire il risultato all'esterno
 * \param VortexConnection *cn Connessione su cui inviare la lista di alert, nel caso in cui *sel non sia NULL
 * \param VortexChannel *ch Canale su cui inviare gli alert nel caso in cui *sel non sia NULL
 * \return xmlNodeList * Lista ordinata contenente gli alert positivi alla ricerca, assume valore NULL nel caso in cui i dati debbano essere inviati direttamente sulla connessione (*sel diverso da NULL)
 */
#ifdef _WIN32 
static xmlNodeList *notTimeFilter(unsigned char sign_mode,int sign_num,int step_num,const char *tstamp, char mode,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#else
xmlNodeList *notTimeFilter(unsigned char sign_mode,int sign_num,int step_num,const char *tstamp, char mode,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	int year,month,day,hour,min,sec,cnt=0;
	int i;
	unsigned char hh,mn,ss,dd,mm;
	long int ts;
	yList *curyear;
	dailyAlertList *curday;
	xmlNodeList *positive;
	AlertList *local;
	
	positive=NULL;
	positive=newxmlNodeList();
	sscanf(tstamp,"%d-%d-%d,%d:%d:%d",&year,&month,&day,&hour,&min,&sec);
	hh=hour;
	mn=min;
	ss=sec;
	dd=day;
	mm=month;
	ts=timestamp(hour,min,sec);
	for(i=0;i<366;i++){
		curyear=modeTime(i,mode);
		while(curyear != NULL){
			curday=curyear->top;
			while(curday!=NULL){
				local=curday->referred;
				if(((local->match[sign_num]&pow2[step_num])==0)^sign_mode && (!((curday->yy==year) && (curday->dd==dd) && (curday->mm==mm) && (curday->ts==ts)))){
					if(sel==NULL){
						setNodePointer(positive,curday->referred);
						cnt++;
					}else{
						visualMessage(sign_num,step_num,curday->referred,sel,cn,ch);
					}
				}
				curday=curday->next;
			}
			curyear=curyear->next;
		}
	}

	return (cnt>0)? positive : freexmlNodeList(positive);
}

/**\brief Filtro su un intervallo temporale negato
 *
 * Effettua la ricerca in base ai due timestamp che vengono passati, restituendo una lista ordinata di tutti gli alert il cui timestamp non è compreso tra essi.
 * \param const char *time I due timestamp da usare per la ricerca codificati come stringa:<br>YYYY-MM-DD,hh:mm:ss|YYYY-MM-DD,hh:mm:ss
 * \param char mode Indica il tipo di timestamp (create, detect, analyzer)
 * \param stringList *sel Lista contenente la query, o NULL per i nodo intermedi dell'albero di esecuzione, che non devono restituire il risultato all'esterno
 * \param VortexConnection *cn Connessione su cui inviare la lista di alert, nel caso in cui *sel non sia NULL
 * \param VortexChannel *ch Canale su cui inviare gli alert nel caso in cui *sel non sia NULL
 * \return xmlNodeList * Lista ordinata contenente gli alert positivi alla ricerca, assume valore NULL nel caso in cui i dati debbano essere inviati direttamente sulla connessione (*sel diverso da NULL)
 */
#ifdef _WIN32 
static xmlNodeList *notbetweenTime(unsigned char sign_mode,int sign_num,int step_num,char *time, char mode,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#else
xmlNodeList *notbetweenTime(unsigned char sign_mode,int sign_num,int step_num,char *time, char mode,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	int year1,month1,day1,hour1,min1,sec1;
	int year2,month2,day2,hour2,min2,sec2;
	int cnt=0,i;
	long int ts1,ts2;
	yList *curyear;
	dailyAlertList *curday;
	xmlNodeList *pos;
	AlertList *local;
	
	pos=NULL;
	pos=newxmlNodeList();
	sscanf(time,"%d-%d-%d,%d:%d:%d|%d-%d-%d,%d:%d:%d",&year1,&month1,&day1,&hour1,&min1,&sec1,&year2,&month2,&day2,&hour2,&min2,&sec2);
	ts1=timestamp(hour1,min1,sec1);
	ts2=timestamp(hour2,min2,sec2);
	
	if(year1>year2){
		sscanf(time,"%d-%d-%d,%d:%d:%d|%d-%d-%d,%d:%d:%d",&year2,&month2,&day2,&hour2,&min2,&sec2,&year1,&month1,&day1,&hour1,&min1,&sec1);
	}else if(year1==year2){
		if(month1>month2){
			sscanf(time,"%d-%d-%d,%d:%d:%d|%d-%d-%d,%d:%d:%d",&year2,&month2,&day2,&hour2,&min2,&sec2,&year1,&month1,&day1,&hour1,&min1,&sec1);
		}else if(month1==month2){
			if(day1>day2){
				sscanf(time,"%d-%d-%d,%d:%d:%d|%d-%d-%d,%d:%d:%d",&year2,&month2,&day2,&hour2,&min2,&sec2,&year1,&month1,&day1,&hour1,&min1,&sec1);
			}else if(day1==day2){
				if(ts1>ts2){
					sscanf(time,"%d-%d-%d,%d:%d:%d|%d-%d-%d,%d:%d:%d",&year2,&month2,&day2,&hour2,&min2,&sec2,&year1,&month1,&day1,&hour1,&min1,&sec1);
				}	
			}
		}	
	}
	
	ts1=timestamp(hour1,min1,sec1);
	ts2=timestamp(hour2,min2,sec2);
	
	for(i=0;i<366;i++){
		curyear=modeTime(i,mode);
		while(curyear != NULL){
			curday=curyear->top;
			while(curday!=NULL){
				local=curday->referred;
				if(((local->match[sign_num]&pow2[step_num])==0)^sign_mode && (!((curday->yy>=year1)&&(curday->mm>=month1)&&(curday->dd>=day1)&&(curday->ts>=ts1) && (curday->yy<=year2)&&(curday->mm<=month2)&&(curday->dd<=day2)&&(curday->ts<=ts2)))){
					if(sel==NULL){
						setNodePointer(pos,curday->referred);
						cnt++;
					}else{
						visualMessage(sign_num,step_num,curday->referred,sel,cn,ch);
					}
				}
				curday=curday->next;
			}
			curyear=curyear->next;
		}
	}

	return (cnt>0)? pos : freexmlNodeList(pos);
}

/**\brief Filtro su un intervallo temporale
 *
 * Effettua la ricerca in base ai due timestamp che vengono passati, restituendo una lista ordinata di tutti gli alert il cui timestamp è compreso tra essi.
 * \param const char *time I due timestamp da usare per la ricerca codificati come stringa:<br>YYYY-MM-DD,hh:mm:ss|YYYY-MM-DD,hh:mm:ss
 * \param char mode Indica il tipo di timestamp (create, detect, analyzer)
 * \param stringList *sel Lista contenente la query, o NULL per i nodo intermedi dell'albero di esecuzione, che non devono restituire il risultato all'esterno
 * \param VortexConnection *cn Connessione su cui inviare la lista di alert, nel caso in cui *sel non sia NULL
 * \param VortexChannel *ch Canale su cui inviare gli alert nel caso in cui *sel non sia NULL
 * \return xmlNodeList * Lista ordinata contenente gli alert positivi alla ricerca, assume valore NULL nel caso in cui i dati debbano essere inviati direttamente sulla connessione (*sel diverso da NULL)
 */
#ifdef _WIN32 
static xmlNodeList *betweenTime(unsigned char sign_mode,int sign_num,int step_num,char *time, char mode,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#else
xmlNodeList *betweenTime(unsigned char sign_mode,int sign_num,int step_num,char *time, char mode,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	int year1,month1,day1,hour1,min1,sec1;
	int year2,month2,day2,hour2,min2,sec2;
	int cnt=0,i;
	long int ts1,ts2;
	yList *curyear;
	dailyAlertList *curday;
	xmlNodeList *pos;
	AlertList *local;
	
	pos=newxmlNodeList();
	sscanf(time,"%d-%d-%d,%d:%d:%d|%d-%d-%d,%d:%d:%d",&year1,&month1,&day1,&hour1,&min1,&sec1,&year2,&month2,&day2,&hour2,&min2,&sec2);
	ts1=timestamp(hour1,min1,sec1);
	ts2=timestamp(hour2,min2,sec2);
	
	if(year1>year2){
		sscanf(time,"%d-%d-%d,%d:%d:%d|%d-%d-%d,%d:%d:%d",&year2,&month2,&day2,&hour2,&min2,&sec2,&year1,&month1,&day1,&hour1,&min1,&sec1);
	}else if(year1==year2){
		if(month1>month2){
			sscanf(time,"%d-%d-%d,%d:%d:%d|%d-%d-%d,%d:%d:%d",&year2,&month2,&day2,&hour2,&min2,&sec2,&year1,&month1,&day1,&hour1,&min1,&sec1);
		}else if(month1==month2){
			if(day1>day2){
				sscanf(time,"%d-%d-%d,%d:%d:%d|%d-%d-%d,%d:%d:%d",&year2,&month2,&day2,&hour2,&min2,&sec2,&year1,&month1,&day1,&hour1,&min1,&sec1);
			}else if(day1==day2){
				if(ts1>ts2){
					sscanf(time,"%d-%d-%d,%d:%d:%d|%d-%d-%d,%d:%d:%d",&year2,&month2,&day2,&hour2,&min2,&sec2,&year1,&month1,&day1,&hour1,&min1,&sec1);
				}	
			}
		}	
	}
	
	ts1=timestamp(hour1,min1,sec1);
	ts2=timestamp(hour2,min2,sec2);
	
	for(i=0;i<366;i++){
		curyear=modeTime(i,mode);
		while(curyear != NULL){
			curday=curyear->top;
			while(curday!=NULL){
				local=curday->referred;
				if(((local->match[sign_num]&pow2[step_num])==0)^sign_mode && ((curday->yy>=year1)&&(curday->mm>=month1)&&(curday->dd>=day1)&&(curday->ts>=ts1) && (curday->yy<=year2)&&(curday->mm<=month2)&&(curday->dd<=day2)&&(curday->ts<=ts2))){
					if(sel==NULL){
						setNodePointer(pos,curday->referred);
						cnt++;
					}else{
						visualMessage(sign_num,step_num,curday->referred,sel,cn,ch);
					}
				}
				curday=curday->next;
			}
			curyear=curyear->next;
		}
	}

	return (cnt>0)? pos : freexmlNodeList(pos);
}

#endif
